﻿using System.Linq;
using Complaint.Models.Dtos;

namespace Complaint.Repositories
{
    public class CategoryRepository : BaseRepository<Category>, IRepository<Category>
    {
        #region IRepository<Category> Members

        public virtual void Create(Category dto)
        {
            ObjectContext.AddToCategory(dto);
            Update(dto);
        }

        public virtual IQueryable<Category> FindAll()
        {
            return ObjectContext.Category;
        }

        public virtual Category FindById(int id)
        {
            return FindAll().FirstOrDefault(c => c.CategoryID == id);
        }

        public virtual IQueryable<Category> FindByName(string name)
        {
            return from category in FindAll()
                   where category.Title == name
                   select category;
        }

        #endregion

        public virtual IQueryable<Category> FindByCategory(int id)
        {
            return from category in FindAll()
                   where category.Parent.CategoryID == id
                   select category;
        }

        public virtual IQueryable<Category> GetCategoryHierarchy(int? id)
        {
            var categories = FindAll().Where(c =>
                (id == null ? c.Parent == null : c.Parent.CategoryID == id)
                );

            foreach (var c in categories)
            {
                PopulateCategory(c);
            }

            return categories;
        }

        private static void PopulateCategory(Category category)
        {
            category.Children.Load();
            
            foreach (var c in category.Children)
            {
                PopulateCategory(c);
            }
        }

        public virtual IQueryable<Category> GetPopularRoots(int count)
        {
            var categories = FindAll()
                                .Include("Organisation.Complaint")
                                .Where(c => c.Parent == null)
                                .OrderByDescending(c => c.Organisation.Sum(o => o.Complaint.Count))
                                .Take(count);

            return categories;
        }
    }
}